var AISLE = cc.Enum({
    UP: 0,
    RIGHT: 1,
    DOWN: 2,
    LEFT: 3,
});

// 本游戏时一个简单的连线游戏.
// 实心圆球设定为电源,空心圆球设定为灯;
// 游戏设定为 6*6 方格

cc.Class({
    extends: cc.Component,

    properties: {  
    },
    // 获取数据
    getData()
    {    
        // 首位对应 类型 A: 空 B: 电源 C: 灯 D: 电线
        // 后四位分别对应上右下左通道口开关
        // 暂时设计为6*6大小
        // 单线
        // var data= [
        //     ['A-0000','A-0000','A-0000','A-0000','A-0000','A-0000'],
        //     ['A-0000','B-0100','D-1010','D-0101','D-1100','A-0000'],
        //     ['A-0000','A-0000','A-0000','A-0000','D-1010','A-0000'],
        //     ['A-0000','A-0000','A-0000','A-0000','D-0101','A-0000'],
        //     ['A-0000','A-0000','A-0000','A-0000','C-1000','A-0000'],
        //     ['A-0000','A-0000','A-0000','A-0000','A-0000','A-0000'],]
        // 双线
        var data= [
            ['A-0000','A-0000','A-0000','A-0000','A-0000','A-0000'],
            ['A-0000','B-0100','D-0101','D-0101','D-0110','A-0000'],
            ['A-0000','A-0000','A-0000','A-0000','D-0101','A-0000'],
            ['A-0000','B-0100','D-0101','D-0011','D-1010','A-0000'],
            ['A-0000','A-0000','A-0000','C-1000','C-1000','A-0000'],
            ['A-0000','A-0000','A-0000','A-0000','A-0000','A-0000'],]
        // 双线交叉 多线交叉 由于设计比较仓促,未仔细考虑(画线设计),结果虽然可以正确显示,但线路显示颜色表示有bug
        // var data= [
        //     ['A-0000','A-0000','A-0000','A-0000','A-0000','A-0000'],
        //     ['A-0000','A-0000','B-0100','D-1100','A-0000','A-0000'],
        //     ['A-0000','B-0100','D-1010','D-2121','D-0011','A-0000'],
        //     ['A-0000','A-0000','A-0000','D-1010','D-0101','A-0000'],
        //     ['A-0000','A-0000','A-0000','C-1000','C-1000','A-0000'],
        //     ['A-0000','A-0000','A-0000','A-0000','A-0000','A-0000'],]

        // 三线交叉
        // var data= [
        //     ['A-0000','A-0000','A-0000','A-0000','A-0000','A-0000'],
        //     ['A-0000','B-0100','D-0101','D-0110','A-0000','A-0000'],
        //     ['A-0000','A-0000','A-0000','D-0101','A-0000','A-0000'],
        //     ['A-0000','A-0000','A-0000','D-0101','A-0000','A-0000'],
        //     ['A-0000','C-0100','D-0101','D-1110','C-0001','A-0000'],
        //     ['A-0000','A-0000','A-0000','A-0000','A-0000','A-0000'],]

        // 四线交叉
        // var data= [
        //     ['A-0000','A-0000','A-0000','A-0000','A-0000','A-0000'],
        //     ['A-0000','B-0100','D-0101','D-0110','A-0000','A-0000'],
        //     ['A-0000','A-0000','A-0000','D-0101','A-0000','A-0000'],
        //     ['A-0000','C-0100','D-0101','D-1111','C-0001','A-0000'],
        //     ['A-0000','A-0000','A-0000','D-0101','A-0000','A-0000'],
        //     ['A-0000','A-0000','A-0000','C-1000','A-0000','A-0000'],]

        // 反转数组     
        // 由于添加最外层数组时,是倒序添加,故反转数组,查看查看更加方便
        return data.reverse();
    },

    onLoad () {
        // 暂存为全局变量,为取用方便
        window.dataArray = this.getData();

        this.noneArray = []; // 空白位置集合
        this.sourceArray = []; // 电源所在位置集合
        this.lampArray = []; // 灯所在位置集合
        this.lineArray = []; // 电线所在位置集合

        this.locationYMax = dataArray.length; // y 方向成员数
        this.locationXMax = dataArray[0].length; // x 方向成员数
        
        for(var y = 0; y < this.locationYMax; y++)
        {
            for(var x = 0; x < this.locationXMax; x++)
            {
                var strContent = dataArray[y][x];
                var tempArray = strContent.split("-");
                var type = tempArray[0]; // 类型
                var aisle = tempArray[1]; // 通道接口开关集合
                
                var location = { x:x, y:y }; //坐标
                switch (type) {
                    case 'A': // 空
                        {
                            this.noneArray.push(location);
                        }
                        break;
                    case 'B': // 电源
                        {
                            this.sourceArray.push(location);
                        }
                        break;        
                    case 'C': // 灯
                        {
                            this.lampArray.push(location);
                        }
                        break;
                    case 'D': // 电线
                        {
                            this.lineArray.push(location);
                        }
                        break;
                }
        
                this.addItem(location,type,aisle,false);
            }
        }

        // 初始化所有与电源连接组合,以及它的历史组合
        this.green = [];
        this.greenHistory = [];
        for(var i = 0; i < this.sourceArray.length; i++)
        {
            this.green.push({
                key: i,
                values: []
            });

            this.greenHistory.push({
                key: i,
                values: []
            });
        }

        this.startSearch();
    },

    /**
     * 
     * @param {*Obj 位置} location 
     * @param {*str 类型} type 
     * @param {*str 通道开关集合} aisle 
     * @param {*bool 通电开关} powerOn 
     */
    // 添加 Item
    addItem(location,type,aisle,powerOn)
    {
        var itemBase = cc.instantiate(cc.globalPrefabs["itemBase"]);
        itemBase.parent = this.node;
        // 处理Item位置
        itemBase.x = this.node.width / this.locationXMax * (location.x+1/2);
        itemBase.y = this.node.height / this.locationYMax * (location.y+1/2);

        itemBase.getComponent("itemBase").init(location,type,aisle,powerOn,this);
    },

    /**
     * 开始查找
     */
    startSearch(clickLocation)
    {
        cc.log('开始搜索');
        //首先获取所有电源位置,以及对应电源出口;
        var sourceArray = this.sourceArray;
        // 保存上次结果
        this.greenHistory = this.deepClone(this.green);

        // 重置保存与电源相连的线的数组
        this.green = [];
        for(var i = 0; i < sourceArray.length; i++)
        {
            this.green.push({
                key: i,
                values: []
            });
        }

        for(var i = 0; i < sourceArray.length; i++)
        {
            for(var  k = 0; k < this.green.length; k++)
            {
                if(i == this.green[k].key)
                {
                    // 添加电源
                    this.green[k].values.push(sourceArray[i])
                }
            }
            
            var value = dataArray[sourceArray[i].y][sourceArray[i].x];
            var tempArray = value.split("-");
            var aisle = tempArray[1];
            var aisleArray = aisle.split("");

            var sourceLocation = this.deepClone(sourceArray[i]);
            cc.log('电源坐标:',sourceArray[i]);

            for(var j = 0; j < aisleArray.length; j++)
            {
                // 如果某个方向通道打开,则该方向位电源出口
                // 通过此出口搜索下一个入口.
                if(aisleArray[j] != 0)
                {
                    cc.log('电源出口:',j)
                    // 确定电源出口 开始查找下个目标入口
                    switch (j) {
                        case AISLE.UP:
                            {
                                this.searchUP(i,j,sourceLocation);
                            }
                            break;
                        case AISLE.RIGHT:
                            {
                                this.searchRIGHT(i,j,sourceLocation);
                            }
                        break;    
                        case AISLE.DOWN:
                            {
                                this.searchDOWN(i,j,sourceLocation);
                            }
                            break;
                        case AISLE.LEFT:
                            {
                                this.searchLEFT(i,j,sourceLocation);
                            }
                            break;
                    }

                }
            }
        }

        clickLocation ? this.syncUI(clickLocation) : this.syncUI();

        cc.log('结束搜索',this.green);
        var self = this;
        setTimeout(function() {
            if(self.getGameResult())
            {
                cc.log("过关")
                if(cc.sys.isBrowser)
                {
                    alert("过关");
                }
            }
        }, 100);  
    },

    // 向上搜索
    searchUP(key,enter,location)
    {
        var dcLocation = this.deepClone(location);
        if(dcLocation.y < this.locationYMax-1)
        {
            // 确定下个查找目标位置
            dcLocation.y = dcLocation.y + 1;
            
            // 确定入口位置
            enter = enter + 2;
            if(enter > 3) {  enter = enter - 4; }

            // 判断类型,并搜索出口
            this.searchExit(key,enter,dcLocation);
        }else{
            cc.log('向上搜索,超出坐标')
        }

    },
    // 向右搜索
    searchRIGHT(key,enter,location)
    {
        var dcLocation = this.deepClone(location);
        if(dcLocation.x < this.locationXMax-1)
        {
            // 确定下个查找目标位置
            dcLocation.x = dcLocation.x + 1;
            // 确定入口位置
            enter = enter + 2;
            if(enter > 3) {  enter = enter - 4; }

            // 判断类型,并搜索出口
            this.searchExit(key,enter,dcLocation);
        }else{
            cc.log('向右搜索,超出坐标')

        }
    },
    // 向下搜索
    searchDOWN(key,enter,location)
    {
        var dcLocation = this.deepClone(location);
        if(dcLocation.y > 0)
        {
            // 确定下个查找目标位置
            dcLocation.y = dcLocation.y - 1;
            // 确定入口位置
            enter = enter + 2;
            if(enter > 3) {  enter = enter - 4; }

            // 判断类型,并搜索出口
            this.searchExit(key,enter,dcLocation);
        }else{
            cc.log('向下搜索,超出坐标')
        }
    },
    // 向左搜索
    searchLEFT(key,enter,location)
    {
        var dcLocation = this.deepClone(location);
        if(dcLocation.x > 0)
        {
            // 确定下个查找目标位置
            dcLocation.x = dcLocation.x - 1;
            // 确定入口位置
            enter = enter + 2;
            if(enter > 3) {  enter = enter - 4; }

            // 判断类型,并搜索出口
            this.searchExit(key,enter,dcLocation);
        }else{
            cc.log('向左搜索,超出坐标')
        }
    },

    // 通过入口 搜索出口
    searchExit(key,enter,location)
    {
        var value = dataArray[location.y][location.x];
        var tempArray = value.split("-");
        var type = tempArray[0];
        var aisle = tempArray[1];
        var aisleArray = aisle.split("");

        switch (type) {
            case 'A': // 空
                break;
            case 'B': // 电源
                {
                    if(aisleArray[enter] != 0)
                    {
                        this.green[key].values.push(location)
                    }
                }
                break;        
            case 'C': // 灯
                {
                    if(aisleArray[enter] != 0)
                    {
                        this.green[key].values.push(location)
                    }
                }
                break;
            case 'D': // 电线
                {
                    if(aisleArray[enter] != 0)
                    {
                        this.green[key].values.push(location)

                        // 获得出口坐标集合 和位置
                        var exitArr = this.searchKeys(enter,aisleArray);
                        var dcLocation = this.deepClone(location);
                        for(var i = 0; i < exitArr.length; i++)
                        {
                            // 确定电流出口 开始查找下个目标入口
                            switch (parseInt(exitArr[i])) {
                                case AISLE.UP:
                                    {
                                        this.searchUP(key,parseInt(exitArr[i]),dcLocation);
                                    }
                                    break;
                                case AISLE.RIGHT:
                                    {
                                        this.searchRIGHT(key,parseInt(exitArr[i]),dcLocation);
                                    }
                                break;    
                                case AISLE.DOWN:
                                    {
                                        this.searchDOWN(key,parseInt(exitArr[i]),dcLocation);
                                    }
                                    break;
                                case AISLE.LEFT:
                                    {
                                        this.searchLEFT(key,parseInt(exitArr[i]),dcLocation);
                                    }
                                    break;
                            }
                        }
                    }
                }
                break;
        }
    },

    // ----- 到此搜索完成 -----

    // 判断游戏通关与否
    // 判断依据 保存的绿色通道中是否包含所有的灯
    // TODO 依照规则处理,同一通道中存在多个电源和灯
    getGameResult()
    {
        var tag = 0;
        var lampArray = this.lampArray;
        var sourceArray = this.sourceArray;
        var green = this.green;
        for(var i = 0; i < sourceArray.length; i++)
        {
            for(var j = 0; j < green[i].values.length; j++)
            {

                for (var k = 0; k < lampArray.length; k++) {
                    if(lampArray[k].x === green[i].values[j].x && lampArray[k].y === green[i].values[j].y)
                    {
                        tag++;
                    }
                }

            }
        }
        
        return tag === lampArray.length
    },

    // 同步UI
    syncUI(clickLocation)
    {
        //首先获取绿色通道
        var sourceArray = this.sourceArray;

        // 判断点击位置是否被包含于绿色通道中
        var includeTag = false;
        if(clickLocation)
        {
            for(var i = 0; i < sourceArray.length; i++)
            {
                var values = this.deepClone(this.green[i].values);
                for(var m = 0; m < values.length; m++)
                {
                    if(values[m].x === clickLocation.x && values[m].y === clickLocation.y)
                    {
                        includeTag = true;
                    }
                }
            }
        }


        for(var i = 0; i < sourceArray.length; i++)
        {
            var valuesHistory = this.deepClone(this.greenHistory[i].values);
            var values = this.deepClone(this.green[i].values);
            // 获得被修改的数组
            var changeValues = this.arrSub(valuesHistory,values);

            // 遍历所有子节点 
            for (var index = 0; index < this.node.childrenCount; index++) {
                var nodeChildren = this.node.children[index];

                // 绿色通道数目改变时
                for (var j = 0; j < changeValues.length; j++) {

                    if(nodeChildren.getComponent("itemBase").location.x === changeValues[j].x && nodeChildren.getComponent("itemBase").location.y === changeValues[j].y)
                    {
                        
                        var strContent = dataArray[changeValues[j].y][changeValues[j].x];
                        var tempArray = strContent.split("-");
                        var type = tempArray[0]; // 类型
                        var aisle = tempArray[1]; // 通道接口开关集合
                        
                        var location = this.deepClone(changeValues[j])
    
                        // 如果当前绿色通道数 大于 历史绿色通道数
                        if(values.length > valuesHistory.length) { 
                            // 设置为绿色
                            nodeChildren.getComponent("itemBase").init(location,type,aisle,true,this);
                        }else {
                            // 设置位灰色
                            nodeChildren.getComponent("itemBase").init(location,type,aisle,false,this);
                        }
                    } 
                }  

                // 处理点击坐标位置
                if(clickLocation && nodeChildren.getComponent("itemBase").location.x === clickLocation.x && nodeChildren.getComponent("itemBase").location.y === clickLocation.y)
                {
                    var strContent = dataArray[clickLocation.y][clickLocation.x];
                    var tempArray = strContent.split("-");
                    var type = tempArray[0]; // 类型
                    var aisle = tempArray[1]; // 通道接口开关集合
                    
                    var location = this.deepClone(clickLocation)
    
                    // 如果当前绿色通道数 大于 历史绿色通道数
                    if(includeTag) { 
                        // 设置为绿色
                        nodeChildren.getComponent("itemBase").init(location,type,aisle,true,this);
                    }else {
                        // 设置位灰色
                        nodeChildren.getComponent("itemBase").init(location,type,aisle,false,this);
                    }
                }
                
            }

        }
    },

    // ----- 工具 -----
    // 查找数组中与 已知下标元素相同 的其它下标集合
    searchKeys(index, targetArray)
    {
        var data = [];
        for (i in targetArray)
        {
            if (i != index && targetArray[i] == targetArray[index])
            {
                data.push(i);
            }
        }
        return data;
    },

    // 深拷贝
    deepClone(obj) {
        // 处理  3种 简单类型 , and null or undefined
        if (null === obj || "object" !== typeof obj) return obj;
        
        // 处理 Date
        if (obj instanceof Date) {
            var copy = new Date();
            copy.setTime(obj.getTime());
            return copy;
        }
        
        // 处理 Array
        if (obj instanceof Array) {
            var copy = [];
            for (var i = 0; i < obj.length; ++i) {
                copy[i] = this.deepClone(obj[i]);
            }
            return copy;
        }

        // 处理 Object
        if (obj instanceof Object) {
            var copy = {};
            for (var attr in obj) {
                if (obj.hasOwnProperty(attr)) copy[attr] = this.deepClone(obj[attr]);
            }
            return copy;
        }
        // 抛出异常
        throw new Error("Unable to copy obj! Its type isn't supported.");
    },

    // 数组相减
    arrSub(arrA,arrB)
    {
        var arr1 = this.deepClone(arrA);
        var arr2 = this.deepClone(arrB);    
        var tag = true;
        if(arr1.length > arr2.length)
        {
            var tag = true;
            for (var i = arr1.length - 1; i >= 0; i--) {
                var a = arr1[i];
                for (var j = arr2.length - 1; j >= 0; j--) {
                    var b = arr2[j];
                    if (a.x == b.x && a.y == b.y) {
                        arr1.splice(i, 1);
                        arr2.splice(j, 1);
                        break;
                    }
                }
            }
        }else if(arr1.length < arr2.length){
            var tag = false;
            for (var i = arr2.length - 1; i >= 0; i--) {
                var a = arr2[i];
                for (var j = arr1.length - 1; j >= 0; j--) {
                    var b = arr1[j];
                    if (a.x == b.x && a.y == b.y) {
                        arr2.splice(i, 1);
                        arr1.splice(j, 1);
                        break;
                    }
                }
            }
        }else{
            arr1 = [];
            arr2 = [];
        }
        return tag ? arr1 : arr2
    },
});

